package com.example.springtransaction.controller;

import com.example.springtransaction.model.LogInfo;
import com.example.springtransaction.model.UserInfo;
import com.example.springtransaction.service.LogService;
import com.example.springtransaction.service.UserService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author : niu niu
 * @version : 1.0.0
 * @date : 2023/5/7 20:17
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private LogService logService;
    //事务管理器
    @Resource
    private DataSourceTransactionManager transactionManager;

    //事务定义
    @Resource
    private TransactionDefinition transactionDefinition;

    @RequestMapping("/add")
    Integer add(UserInfo userInfo){
        if (userInfo==null || !StringUtils.hasLength(userInfo.getUsername())
            || !StringUtils.hasLength(userInfo.getPassword())){
            return 0;
        }
        //启动事务
        TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);

        int result = userService.add(userInfo);
        System.out.println("添加 ：" + result);

        //回滚事务
//        transactionManager.rollback(transaction);
        //提交事务
        transactionManager.commit(transaction);
        return result;
    }

    @Transactional //使用注解，自动提交事务
    @RequestMapping("/insert")
    // 注意只支持public方法
    public Integer insert(UserInfo userInfo){
        if (userInfo==null || !StringUtils.hasLength(userInfo.getUsername())
            || !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }
        int result = userService.add(userInfo);
        System.out.println("insert : " + result);
//        int num = 1/0; //出现异常，自动回滚
        //无异常自动提交

        try {
            //注意:当异常被捕获，则不会自动回滚 、
            //解决方案： 1.  捕获后 直接throw 出去 （不可取）
            //          2. 手动回滚事务
            int num = 1/0;

        } catch (Exception e) {
            System.out.println(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }

    /**
     * 需要给被调用的方法设置，调用者不用设置
     * //不设置默认是 REQUIRED 当做调用者整体 ； 全部回滚
     * //设置为REQUIRES_NEW，则单独是一个事务，调用者有事务，则先挂起。执行自己的事务
     * //NOT_SUPPORTED ,以非事务的方式运行
     * //NEST ，嵌套方式，自己事务内，又自己处理，回滚也是仅仅自己事务
     * 比如外部的方法A，里面调用了方法B，在B使用了Propagation.NESTED ，
     * 如果对这个B进行了异常处理，则只对B进行内部事务回滚
     *  如果不进行异常处理，就是A整个进行事务回滚
     * @param userInfo
     * @return
     */
    @Transactional(propagation = Propagation.NESTED)
    @RequestMapping("/add2") //不设置默认是 REQUIRED 当做调用者整体
    public Integer add2(UserInfo userInfo){
        if (userInfo==null || !StringUtils.hasLength(userInfo.getUsername())
        || !StringUtils.hasLength(userInfo.getPassword())){
            return 0;
        }
        int result  = userService.add(userInfo);
        System.out.println("添加用户结果 ：" + result);
        LogInfo logInfo = new LogInfo();
        logInfo.setName("添加用户 : " + userInfo.getUsername());
        logInfo.setDetail("添加用户结果 ：" + result);
        Integer logResult = logService.add(logInfo);
        return result;
    }
}
